package com.alinks.modbus.core.frame;

import com.alinks.modbus.core.exception.ModbusSlaveCodeEnum;
import com.alinks.modbus.core.utils.CRC16;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

public class RtuFrame extends ModbusFrame {
    /**
     * Rx:000006-01 03 00 00 00 0A C5 CD
     * Tx:000007-01 03 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A3 67
     *
     * Header + 协议格式+CRC
     */

    @Setter
    @Getter
    @Builder
    public static class Request extends ModbusFrame {
        /**
         * MBAP header 报文头
         */
        private Header header;

        private RequestBody body;

        private short crc;

        private Except except;



        public void check() {
            if (body == null) {
                TcpFrame.Except except = TcpFrame.Except.builder()
                        .func((byte)(body.getFunc() | 0x80))
                        .exceptCode(ModbusSlaveCodeEnum.EXCEPT_01)
                        .build();
                this.except = except;
            } else {
                byte[] readBytes = new byte[getReadLength()];
                readBytes[0] = ((RtuHeader)header).unitId;
                body.getbodyBytes(readBytes, 0);
                //0x01,0x03, 0x00, 0x00, 0x00, 0x0a
                int calcCrc = CRC16.calc(readBytes);
                if ((crc & 0xff) != (calcCrc >> 8 & 0xff) || (crc >> 8 & 0xff) != (calcCrc & 0xff)) {
                    TcpFrame.Except except = TcpFrame.Except.builder()
                            .func((byte)(body.getFunc() | 0x80))
                            .exceptCode(ModbusSlaveCodeEnum.EXCEPT_03)
                            .build();
                    this.except = except;
                }
            }
        }
    }

    @Setter
    @Getter
    @Builder
    public static class Response extends ModbusFrame {
        /**
         * MBAP header 报文头
         */
        private Header header;

        private ResponseBody body;

        private short crc;

        private Except except;

    }

    @Setter
    @Getter
    @Builder
    public static class RtuHeader extends Header {
        /**
         * 单元标识
         */
        protected byte unitId;

        /**
         * 获取头字节数组
         * @return
         */
        @Override
        public byte[] getHeaderBytes() {
            return new byte[]{
                    unitId
            };
        }
    }
}
